File upload corruption

Viewed 1112

Im trying to upload a file to sharepoint

  1. Successful try with just axios is the following enter image description here

  2. Failure if i upload using Guzzle enter image description here enter image description here

Uploaded file at the end is corrupted

enter image description here

5 Answers

There are a few things you need to modify to get this working (tested on my end):

  1. To get the contents of the file, you need $request->file('file') and then use file_get_contents() on it. You can lose the get() part.

  2. Make sure you're sending the header to accept multipart/form-data too:

    "Accept" => "multipart/form-data"
    
  3. Fields name and filename in a form are two different things. Former is the name of the field while the latter is the name of the file. You need to send both.

Try this:

protected function uploadFile(Request $request){
$file = $request->file('file');
$body = [
          "headers" => [
          "Accept" => "multipart/form-data",
          "Authorization" => "Bearer {$this->token}"
         ],
         "multipart" => [
          "name" => "file",
          "contents" => file_get_contents($file),
          "filename" => $file->getClientOriginalName()
        ]
     ];
return (new Client)->request('POST', 'https://.sharepoint.com/...', $body);
}

P.S. - You can check whether a file is valid or not using isValid():

if ($request->file('file')->isValid()) {
    //
}

Official docs on this: https://laravel.com/docs/7.x/requests#retrieving-uploaded-files

When providing content to be uploaded to Guzzle client as string, Guzzle tries to infer necessary information about the file such as filename, content-type.

You can help Guzzle to infer these information correctly to build the multipart request by passing information about about the filename and content-type in the multipart payload.

[
    //...

    'multipart' => [
        [
            'name' => 'fileName',
            'contents' => $request->file('file')->get(),
            'filename' => $request->file('file')->getName(),
            'headers' => [
               'content-type' => $request->file('file')->getMimeType(),
            ]
        ]
    ]
]

Add content-type as blob.

axios.post(
    'https://sharepoint....'
    ,data.get('file')
    {
        'headers' {
            'Authorization': `Bearer ${this.token}`
            ,'Content-Type': 'blob',
         }
    }
)

Try something like this. Remove the ->get() of your $request->file()

//Get the file object from the request.
$file = $request->file('file');

//Make the request
return (new Client)->request('POST', 'https://.sharepoint.com/sites....', [
    'headers'      => [ 'Authorization' => "Bearer {$this->token}" ],
    'multipart' => [
        [
            'name'     => 'FileContents',
            'contents' => $file,
            'filename' => $file->getClientOriginalName()
        ],
        
    ],
]);

In my opinion, you should store it somewhere in your local server temporarily first, and then you sent that file to sharepoint, deleted the temporary file, I think if you send it right away without storing it, the file will be corrupted. Please try the way below

$file = $request->file('logo');
$original_name = $file->getClientOriginalName(); // get original file
$name = time() . '_' . $original_name; // store it in different name so it would not be duplicated
$path = base_path() .'/public_html/your_project/public/temporary/'; // full path of file folder
// store the uploaded file
$file->move($path, $name);
$body = [
          "headers" => [
          "Authorization" => "Bearer {$this->token}"
         ],
         "multipart" => [
          "name" => "logo",
          "contents" => fopen($path . $name, 'r')
        ]
     ];
$response = (new Client)->request('POST', 'https://.sharepoint.com/...', $body);
// remove the file after done
unlink($path . $name);
return $response;

Hope this would work for you! Please correct me if I was wrong

Related