1
mirror of https://github.com/rclone/rclone synced 2024-10-07 15:17:14 +02:00

opendrive: refactor to use existing lib/rest facilities for uploads

This also checks the return of the call to make sure the number of
bytes written was as expected.
This commit is contained in:
Nick Craig-Wood 2019-07-23 14:20:51 +01:00
parent 71587344c6
commit 493dfb68fd
2 changed files with 21 additions and 68 deletions

View File

@ -1,11 +1,9 @@
package opendrive
import (
"bytes"
"context"
"fmt"
"io"
"mime/multipart"
"net/http"
"net/url"
"path"
@ -947,84 +945,35 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
fs.Debugf(o, "Uploading chunk %d, size=%d, remain=%d", chunkCounter, currentChunkSize, remainingBytes)
chunk := readers.NewRepeatableLimitReaderBuffer(in, buf, currentChunkSize)
var reply uploadFileChunkReply
err = o.fs.pacer.Call(func() (bool, error) {
// seek to the start in case this is a retry
if _, err = chunk.Seek(0, io.SeekStart); err != nil {
return false, err
}
var formBody bytes.Buffer
w := multipart.NewWriter(&formBody)
fw, err := w.CreateFormFile("file_data", o.remote)
if err != nil {
return false, err
}
if _, err = io.Copy(fw, chunk); err != nil {
return false, err
}
// Add session_id
if fw, err = w.CreateFormField("session_id"); err != nil {
return false, err
}
if _, err = fw.Write([]byte(o.fs.session.SessionID)); err != nil {
return false, err
}
// Add session_id
if fw, err = w.CreateFormField("session_id"); err != nil {
return false, err
}
if _, err = fw.Write([]byte(o.fs.session.SessionID)); err != nil {
return false, err
}
// Add file_id
if fw, err = w.CreateFormField("file_id"); err != nil {
return false, err
}
if _, err = fw.Write([]byte(o.id)); err != nil {
return false, err
}
// Add temp_location
if fw, err = w.CreateFormField("temp_location"); err != nil {
return false, err
}
if _, err = fw.Write([]byte(openResponse.TempLocation)); err != nil {
return false, err
}
// Add chunk_offset
if fw, err = w.CreateFormField("chunk_offset"); err != nil {
return false, err
}
if _, err = fw.Write([]byte(strconv.FormatInt(chunkOffset, 10))); err != nil {
return false, err
}
// Add chunk_size
if fw, err = w.CreateFormField("chunk_size"); err != nil {
return false, err
}
if _, err = fw.Write([]byte(strconv.FormatInt(currentChunkSize, 10))); err != nil {
return false, err
}
// Don't forget to close the multipart writer.
// If you don't close it, your request will be missing the terminating boundary.
err = w.Close()
if err != nil {
return false, err
}
opts := rest.Opts{
Method: "POST",
Path: "/upload/upload_file_chunk.json",
Body: &formBody,
ExtraHeaders: map[string]string{"Content-Type": w.FormDataContentType()},
Body: chunk,
MultipartParams: url.Values{
"session_id": []string{o.fs.session.SessionID},
"file_id": []string{o.id},
"temp_location": []string{openResponse.TempLocation},
"chunk_offset": []string{strconv.FormatInt(chunkOffset, 10)},
"chunk_size": []string{strconv.FormatInt(currentChunkSize, 10)},
},
MultipartContentName: "file_data", // ..name of the parameter which is the attached file
MultipartFileName: o.remote, // ..name of the file for the attached file
}
resp, err = o.fs.srv.Call(&opts)
resp, err = o.fs.srv.CallJSON(&opts, nil, &reply)
return o.fs.shouldRetry(resp, err)
})
if err != nil {
return errors.Wrap(err, "failed to create file")
}
err = resp.Body.Close()
if err != nil {
return errors.Wrap(err, "close failed on create file")
if reply.TotalWritten != currentChunkSize {
return errors.Errorf("failed to create file: incomplete write of %d/%d bytes", reply.TotalWritten, currentChunkSize)
}
chunkCounter++

View File

@ -212,3 +212,7 @@ type permissions struct {
FileID string `json:"file_id"`
FileIsPublic int64 `json:"file_ispublic"`
}
type uploadFileChunkReply struct {
TotalWritten int64 `json:"TotalWritten"`
}