Golang io.copier deux fois sur le corps de la requête
Je suis la construction d'un système de stockage d'objets blob et j'ai choisi d'Aller comme langage de programmation.
- Je créer un flux pour faire un multipart upload de fichier du client vers le blob serveur.
Le stream fonctionne très bien, mais je veux faire un hash sha1 de le corps de la requête. J'ai besoin de io.Copiez le corps par deux fois. Le sha1 est créé mais la multipart flux de 0 octets après.
- Pour la création de la table de hachage
- Pour le streaming, le corps comme multipart
une idée de comment je peux faire cela?
le client de téléchargement
func (c *Client) Upload(h *UploadHandle) (*PutResult, error) {
body, bodySize, err := h.Read()
if err != nil {
return nil, err
}
//Creating a sha1 hash from the bytes of body
dropRef, err := drop.Sha1FromReader(body)
if err != nil {
return nil, err
}
bodyReader, bodyWriter := io.Pipe()
writer := multipart.NewWriter(bodyWriter)
errChan := make(chan error, 1)
go func() {
defer bodyWriter.Close()
part, err := writer.CreateFormFile(dropRef, dropRef)
if err != nil {
errChan <- err
return
}
if _, err := io.Copy(part, body); err != nil {
errChan <- err
return
}
if err = writer.Close(); err != nil {
errChan <- err
}
}()
req, err := http.NewRequest("POST", c.Server+"/drops/upload", bodyReader)
req.Header.Add("Content-Type", writer.FormDataContentType())
resp, err := c.Do(req)
if err != nil {
return nil, err
}
.....
}
le sha1 func
func Sha1FromReader(src io.Reader) (string, error) {
hash := sha1.New()
_, err := io.Copy(hash, src)
if err != nil {
return "", err
}
return hex.EncodeToString(hash.Sum(nil)), nil
}
télécharger poignée
func (h *UploadHandle) Read() (io.Reader, int64, error) {
var b bytes.Buffer
hw := &Hasher{&b, sha1.New()}
n, err := io.Copy(hw, h.Contents)
if err != nil {
return nil, 0, err
}
return &b, n, nil
}
Je l'ai fait pour travailler merci à @OneofOne je poste le résultat final plus tard, quand j'ai nettoyé les dégâts que j'ai faite
Vous n'avez pas vraiment besoin de beaucoup de code et vous certainement n'avez pas besoin de stocker un ensemble contigu copie de votre blob dans la mémoire RAM. J'ai fait une chose similaire avec multi-GO gouttes sur la mémoire vive de faim appareils sans problème.
que feriez-vous dans ce cas?
Que faites-vous avec les trucs que vous écrivez dans ce buffer? Le faire sans l'écrire dans la mémoire tampon. Envisagez de cette aire de jeu lien -- qui ne fonctionne pas sur le terrain de jeu parce que vous ne pouvez pas créer de fichiers, mais peut manipuler arbitrairement long entrées correctement avec un minimum de l'utilisation de la mémoire. J'ai fait une chose similaire pour un CAS qui a également vérifié l'extérieur de la bande de hachage, puis renommé le fichier après la clôture avec succès.
Comme alternative, vous pouvez utiliser cette bibliothèque https://github.com/hyperboloide/sprocess pour traiter de téléchargement de fichiers torrents
Vous n'avez pas vraiment besoin de beaucoup de code et vous certainement n'avez pas besoin de stocker un ensemble contigu copie de votre blob dans la mémoire RAM. J'ai fait une chose similaire avec multi-GO gouttes sur la mémoire vive de faim appareils sans problème.
que feriez-vous dans ce cas?
Que faites-vous avec les trucs que vous écrivez dans ce buffer? Le faire sans l'écrire dans la mémoire tampon. Envisagez de cette aire de jeu lien -- qui ne fonctionne pas sur le terrain de jeu parce que vous ne pouvez pas créer de fichiers, mais peut manipuler arbitrairement long entrées correctement avec un minimum de l'utilisation de la mémoire. J'ai fait une chose similaire pour un CAS qui a également vérifié l'extérieur de la bande de hachage, puis renommé le fichier après la clôture avec succès.
Comme alternative, vous pouvez utiliser cette bibliothèque https://github.com/hyperboloide/sprocess pour traiter de téléchargement de fichiers torrents
OriginalL'auteur Anthony De Meulemeester | 2014-09-04
Vous devez vous connecter pour publier un commentaire.
Vous ne pouvez pas le faire directement, mais vous pouvez écrire un wrapper qui ne le hachage sur io.Copie
//version mise à jour basé sur @Dustin commentaire depuis que je complète oublié
io.TeeReader
existé.hachage écrit sont garantis de ne pas renvoyer des erreurs. L'échelle de la ville 6 heures de coupures sont amusants
aucune idée de comment la mettre en œuvre? j'ai ajouté le uploadhandle lire func
J'ai mis à jour le code et ajout d'un exemple. Je tiens à souligner que votre code est ouvert à des attaques de DoS puisque vous garder le fichier en mémoire (en octets.Tampon) et quelqu'un peut garder le téléchargement de gros fichiers.
J'ai posté un aire de jeux lien avec un beaucoup plus petit et moins cher mécanisme. (la moitié du code est un test d'io.Lecteur juste à produire de la sortie). Ce code réinvente
io.TeeReader
, mais avec une beaucoup plus précis, encore plus facile de se tromper avec l'API.OriginalL'auteur OneOfOne
Je voudrais suggérer à l'aide d'un
io.TeeReader
si vous voulez pousser toutes les lectures de la goutte par le sha1 simultanément.Maintenant que le bodyReader est consommé au cours du chargement, le hachage est automatiquement mis à jour.
OriginalL'auteur JimB
Vous avez deux options.
La façon la plus directe est d'utiliser
io.MultiWriter
.Mais si vous avez besoin de la valeur de hachage pour produire le multipart de sortie, puis vous devrez le copier à un
bytes.Buffer
et puis écrire la mémoire tampon à chaque écrivain.OriginalL'auteur andlabs